<html>
<head><meta charset="utf-8"><title>serde: strange union types · general · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/index.html">general</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/serde.3A.20strange.20union.20types.html">serde: strange union types</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="228771359"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/serde%3A%20strange%20union%20types/near/228771359" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Anatol Ulrich <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/serde.3A.20strange.20union.20types.html#228771359">(Mar 04 2021 at 13:28)</a>:</h4>
<p>I have an incoming webhook event stream of loosely/complex typed objects. As a result I want to view each one using several "lenses". In concrete terms, every item has a <code>task_id</code> field, so I have a <code>struct TaskRef { task_id: String }</code>, but also they're (serde-speak) adjacently tagged enums, so I'm also treating them as <code>pub enum Event {A, B, ...}</code>. Currently I'm solving this by parsing twice: </p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="n">tr</span>: <span class="nc">TaskRef</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">serde_json</span>::<span class="n">from_str</span><span class="p">(</span><span class="n">event</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
<span class="c1">// do task-related things ...</span>

<span class="kd">let</span><span class="w"> </span><span class="n">e</span>: <span class="nc">Event</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">serde_json</span>::<span class="n">from_str</span><span class="p">(</span><span class="n">event</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
<span class="k">match</span><span class="w"> </span><span class="n">e</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* ... */</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>this seems a bit cumbersome. Can I somehow build a union type?</p>



<a name="228771775"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/serde%3A%20strange%20union%20types/near/228771775" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/serde.3A.20strange.20union.20types.html#228771775">(Mar 04 2021 at 13:31)</a>:</h4>
<p>Why not have <code>struct Event { task_id: String, kind: EventKind }</code>, <code>enum EventKind {A, B, ...}</code> for your data representation? That way you can keep both the commonality of <code>task_id</code> in every event while still having the separation into event kinds</p>



<a name="228771799"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/serde%3A%20strange%20union%20types/near/228771799" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Anatol Ulrich <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/serde.3A.20strange.20union.20types.html#228771799">(Mar 04 2021 at 13:31)</a>:</h4>
<p>unfortunately I can't control the data format</p>



<a name="228771833"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/serde%3A%20strange%20union%20types/near/228771833" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/serde.3A.20strange.20union.20types.html#228771833">(Mar 04 2021 at 13:31)</a>:</h4>
<p>I mean the data structure format</p>



<a name="228771910"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/serde%3A%20strange%20union%20types/near/228771910" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Anatol Ulrich <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/serde.3A.20strange.20union.20types.html#228771910">(Mar 04 2021 at 13:32)</a>:</h4>
<p>oh! ok, trying</p>



<a name="228771918"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/serde%3A%20strange%20union%20types/near/228771918" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/serde.3A.20strange.20union.20types.html#228771918">(Mar 04 2021 at 13:32)</a>:</h4>
<p>this doesn't mean serde should parse the input differently</p>



<a name="228771977"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/serde%3A%20strange%20union%20types/near/228771977" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Anatol Ulrich <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/serde.3A.20strange.20union.20types.html#228771977">(Mar 04 2021 at 13:32)</a>:</h4>
<p>I probably need to flatten then?</p>



<a name="228772053"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/serde%3A%20strange%20union%20types/near/228772053" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/serde.3A.20strange.20union.20types.html#228772053">(Mar 04 2021 at 13:33)</a>:</h4>
<p>I'm not too familiar with serde but I get the sense it has enough knobs on it to make a parser for this</p>



<a name="228772094"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/serde%3A%20strange%20union%20types/near/228772094" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Anatol Ulrich <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/serde.3A.20strange.20union.20types.html#228772094">(Mar 04 2021 at 13:33)</a>:</h4>
<p>I'm asking in the first place because the way I'm reading the docs it seems there is not</p>



<a name="228772099"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/serde%3A%20strange%20union%20types/near/228772099" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Anatol Ulrich <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/serde.3A.20strange.20union.20types.html#228772099">(Mar 04 2021 at 13:33)</a>:</h4>
<p>but I'll try flatten</p>



<a name="228772239"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/serde%3A%20strange%20union%20types/near/228772239" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/serde.3A.20strange.20union.20types.html#228772239">(Mar 04 2021 at 13:34)</a>:</h4>
<p>Do you have a simple example?</p>



<a name="228772710"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/serde%3A%20strange%20union%20types/near/228772710" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/serde.3A.20strange.20union.20types.html#228772710">(Mar 04 2021 at 13:37)</a>:</h4>
<p>worst case scenario, you can implement <code>Deserialize</code> manually for your struct, and map it into serde's data model any way you like</p>



<a name="228772783"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/serde%3A%20strange%20union%20types/near/228772783" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Anatol Ulrich <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/serde.3A.20strange.20union.20types.html#228772783">(Mar 04 2021 at 13:38)</a>:</h4>
<p>relevant <a href="https://serde.rs/enum-representations.html">serde docs</a> (see adjacently tagged)</p>
<p>data:</p>
<div class="codehilite" data-code-language="JSON"><pre><span></span><code><span class="p">{</span>
    <span class="nt">"task_id"</span><span class="p">:</span> <span class="s2">"f71f4m"</span><span class="p">,</span>
    <span class="nt">"event"</span><span class="p">:</span> <span class="s2">"taskCommentUpdated"</span><span class="p">,</span>
    <span class="nt">"history_items"</span><span class="p">:</span> <span class="p">[</span>
    <span class="p">{</span>
        <span class="nt">"id"</span><span class="p">:</span> <span class="s2">"2333164701594231585"</span><span class="p">,</span>
        <span class="nt">"type"</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
        <span class="nt">"date"</span><span class="p">:</span> <span class="s2">"1614863592863"</span><span class="p">,</span>
        <span class="nt">"field"</span><span class="p">:</span> <span class="s2">"comment"</span><span class="p">,</span>
<span class="err">...</span>
</code></pre></div>
<p>code:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="cp">#[derive(Deserialize, Debug)]</span><span class="w"></span>
<span class="cp">#[serde(tag = </span><span class="s">"event"</span><span class="cp">, content = </span><span class="s">"history_items"</span><span class="cp">)]</span><span class="w"></span>
<span class="k">pub</span><span class="w"> </span><span class="k">enum</span> <span class="nc">Event</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="cp">#[serde(rename(deserialize = </span><span class="s">"taskCommentUpdated"</span><span class="cp">))]</span><span class="w"></span>
<span class="w">    </span><span class="n">TaskCommentUpdated</span><span class="p">(</span><span class="nb">Vec</span><span class="o">&lt;</span><span class="n">TaskCommentUpdate</span><span class="p">(</span><span class="n">e</span><span class="o">&gt;</span><span class="p">),</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="cp">#[derive(Deserialize, Debug)]</span><span class="w"></span>
<span class="k">pub</span><span class="w"> </span><span class="k">struct</span> <span class="nc">TaskCommentUpdate</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">pub</span><span class="w"> </span><span class="n">field</span>: <span class="nb">String</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="k">pub</span><span class="w"> </span><span class="n">date</span>: <span class="nb">String</span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="228773070"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/serde%3A%20strange%20union%20types/near/228773070" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Anatol Ulrich <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/serde.3A.20strange.20union.20types.html#228773070">(Mar 04 2021 at 13:39)</a>:</h4>
<p>you're right, a manual <code>Deserialize</code> would work. I'd just like to avoid this. Trying out flattening ... this might actually work, sec</p>



<a name="228775468"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/serde%3A%20strange%20union%20types/near/228775468" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Anatol Ulrich <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/serde.3A.20strange.20union.20types.html#228775468">(Mar 04 2021 at 13:54)</a>:</h4>
<p><span class="user-mention" data-user-id="271719">@Mario Carneiro</span> indeed, flatten does the trick! Thanks!</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>